package com.blockchain.front.service.common.achieve;

import java.security.SecureRandom;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.UnixCrypt;

import com.blockchain.common.enums.CertificateType;
import com.blockchain.common.enums.IsPass;
import com.blockchain.common.enums.LoginStatus;
import com.blockchain.common.enums.XlbType;
import com.blockchain.framework.config.ConfigureProvider;
import com.blockchain.framework.http.session.authentication.AuthenticationException;
import com.blockchain.framework.http.upload.FileStore;
import com.blockchain.framework.service.ServiceFactory;
import com.blockchain.framework.service.ServiceResource;
import com.blockchain.framework.service.exception.LogicalException;
import com.blockchain.framework.service.exception.ParameterException;
import com.blockchain.framework.service.query.ArrayParser;
import com.blockchain.framework.service.query.ItemParser;
import com.blockchain.front.config.FrontConst;
import com.blockchain.front.service.common.UserManage;
import com.blockchain.front.service.common.entity.User;
import com.blockchain.front.service.common.entity.UserInsert;
import com.blockchain.front.util.MD5;
import com.blockchain.util.StringHelper;
import com.blockchain.util.parser.EnumParser;
import com.blockchain.util.parser.IntegerParser;
import com.blockchain.variables.P2PConst;
import com.blockchain.variables.defines.SystemVariable;

public class UserManageImpl extends AbstractCommonService implements UserManage {

	public static class UserManageFactory implements ServiceFactory<UserManage> {

		@Override
		public UserManage newInstance(ServiceResource serviceResource) {
			return new UserManageImpl(serviceResource);
		}
	}

	public UserManageImpl(ServiceResource serviceResource) {
		super(serviceResource);
	}

	@Override
	public int addUser(UserInsert user) throws Throwable {
		
		serviceResource.openTransactions();
		/**
		 * 用户账号表
		 */
		String t6010 = "INSERT INTO T6010 SET F02=?,F03=?,F04=?";
		/**
		 * 用户基础信息表
		 */
		String t6011 = "INSERT INTO T6011 SET F01=?,F06=?,F07=?,F09=CURRENT_TIMESTAMP()";
		/**
		 * 用户资金信息表
		 */
		String t6023 = "INSERT INTO T6023 SET F01=?";
		
		if (user == null) {
			throw new ParameterException("err_1008");
		}
		
		if (isAccountExists(user.getPhone())) {
			throw new LogicalException("err_1010");	
		}
		// 查询服务码
		String selectT6011 = "SELECT F07 FROM T6011";
		String myCode = getCode();
		String code = user.getCode();
		boolean isExists = false;
		try (Connection connection = getConnection(FrontConst.DB_USER)) {
			try (PreparedStatement ps = connection.prepareStatement(selectT6011)) {
				try (ResultSet rs = ps.executeQuery()) {
					while (rs.next()) {
						String s = rs.getString(1);
						if (!StringHelper.isEmpty(s) && s.equals(code)) {
							isExists = true;
						}
						if (!StringHelper.isEmpty(s) && s.equals(myCode)) {
							myCode = getCode();
						}
					}
				}
			}
		}
		if (!isExists) {
			code = "";
		}
		String password = UnixCrypt.crypt(user.getPassword(), DigestUtils.sha256Hex(user.getPassword()));
		int userId = insert(getConnection(P2PConst.DB_USER), t6010, user.getPhone(), password, user.getPhone());
		if (userId > 0) {
			execute(getConnection(P2PConst.DB_USER), t6011, userId, code, myCode);
			execute(getConnection(P2PConst.DB_USER), t6023, userId);
		}
		
		
		return userId;
	}
	@Override
	public boolean isAccountExists(String accountName) throws Throwable {
		String sql = "SELECT F01 FROM T6010 WHERE F02=? OR F04=?";
		try (PreparedStatement ps = getConnection(FrontConst.DB_USER).prepareStatement(sql)) {
			ps.setString(1, accountName);
			ps.setString(2, accountName);
			try (ResultSet rs = ps.executeQuery()) {
				if (rs.next()) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public String getAccountName() throws Throwable {
		try (Connection connection = getConnection(FrontConst.DB_USER)) {
			try (PreparedStatement pstmt = connection.prepareStatement("SELECT F02 FROM T6010 WHERE F01 = ?")) {
				pstmt.setInt(1, serviceResource.getSession().getAccountId());
				try (ResultSet resultSet = pstmt.executeQuery()) {
					if (resultSet.next()) {
						return resultSet.getString(1);
					}
					return null;
				}
			}
		}
	}

	@Override
	public int readAccountId(String condition, String password) throws AuthenticationException, SQLException {
		int accountId = 0;
		String sql = "SELECT F01,F03,F06 FROM T6010 WHERE F02=? OR F04=? OR F05=?";
		try (Connection connection = getConnection(FrontConst.DB_USER)) {
			try (PreparedStatement ps = connection.prepareStatement(sql)) {
				ps.setString(1, condition);
				ps.setString(2, condition);
				ps.setString(3, condition);
				try (ResultSet rs = ps.executeQuery()) {
					if (rs.next()) {
						accountId = rs.getInt(1);
						String pwd = rs.getString(2);
						String status = rs.getString(3);
						if ("S".equals(status)) {
							throw new AuthenticationException("err_1011");
						}
						String md5password=MD5.getMd5Value(password);
						if (md5password.equals(pwd)) {
							execute(getConnection(FrontConst.DB_USER), "UPDATE T6010 SET F03=? WHERE F01=?",
									UnixCrypt.crypt(password, DigestUtils.sha256Hex(password)), accountId);
						} else {
							if (!UnixCrypt.crypt(password, DigestUtils.sha256Hex(password)).equals(pwd)) {
								throw new AuthenticationException("err_1012");
							}
						}
					} else {
						throw new AuthenticationException("err_1012");
					}
				}
			}
		}
		return accountId;
	}

	@Override
	public void log(int accountId, String ip) throws Throwable {
		String t6051 = "INSERT INTO T6051 SET F02=?,F03=?,F04=?,F05=?";
		String t6010 = "SELECT F02 FROM T6010 WHERE F01=?";
		String updateT6011 = "UPDATE T6011 SET F10=? WHERE F01=?";
		Timestamp now = new Timestamp(System.currentTimeMillis());
		String name = "";
		try (Connection connection = getConnection(FrontConst.DB_USER)) {
			try (PreparedStatement ps = connection.prepareStatement(t6010)) {
				ps.setInt(1, accountId);
				try (ResultSet rs = ps.executeQuery()) {
					if (rs.next()) {
						name = rs.getString(1);
					}
				}
			}
			try (PreparedStatement ps = connection.prepareStatement(t6051)) {
				ps.setString(1, name);
				ps.setTimestamp(2, now);
				ps.setString(3, ip);
				ps.setString(4, accountId <= 0 ? LoginStatus.SB.name() : LoginStatus.CG.name());
				ps.execute();
			}
		}
		execute(getConnection(FrontConst.DB_USER), updateT6011, now, accountId);
	}

	private String getCode() {
		char[] chs = { 'a', 'c', '3', '4', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p', 'r', 't', 'u', 'v',
				'w', 'x', 'y', '7', '8' };
		SecureRandom random = new SecureRandom();
		final char[] value = new char[6];
		for (int i = 0; i < 6; i++) {
			value[i] = (char) chs[random.nextInt(chs.length)];
		}
		final String code = new String(value);
		return code;
	}

	@Override
	public boolean isPhone(String idCard) throws Throwable {
		return select(getConnection(FrontConst.DB_USER), new ItemParser<Boolean>() {
			@Override
			public Boolean parse(ResultSet rs) throws SQLException {
				boolean is = false;
				if (rs.next()) {
					is = true;
				}
				return is;
			}
		}, "SELECT F01 FROM T6010 WHERE F04=? OR F02=?", idCard,idCard);
	}

	@Override
	public void updateSend(String phone, String code) throws Throwable {
		/*
		 * if (isHmd(phone)) { throw new ParameterException("您已加入黑名单，请联系客服！"); }
		 */
		ConfigureProvider configureProvider = serviceResource.getResource(ConfigureProvider.class);
		int count = this.getSend(phone);
		if (count >= IntegerParser.parse(configureProvider.getProperty(SystemVariable.DX_RZCS))) {
			/* addHmd(phone); */
			throw new ParameterException("err_1013");
		}
		serviceResource.openTransactions();

		if (getSendSec(phone, "999999999", 60) > 0) {
			throw new ParameterException("err_1014");
		}

		insert(getConnection(FrontConst.DB_USER), "INSERT INTO T6058 SET F02=?,F03=?,F04=NOW(),F05=NOW(),F06=? ", phone,
				code, "999999999");
	}

	/*
	private void addHmd(String phone) throws Throwable {
		String s = "INSERT INTO T6010_1 SET F01=?,F02=CURRENT_TIMESTAMP() ON DUPLICATE KEY UPDATE F02=CURRENT_TIMESTAMP(),F03=1 ";
		try (Connection c = getConnection(P2PConst.DB_USER)) {
			execute(getConnection(P2PConst.DB_USER), s, phone);
			c.commit();
		}
	}*/
	 
	/*private boolean isHmd(String phone) throws Throwable {
		boolean count = false;
		count = select(getConnection(P2PConst.DB_USER), new ItemParser<Boolean>() {

			@Override
			public Boolean parse(ResultSet res) throws SQLException {
				if (res.next()) {
					return res.getInt(1) > 0 ? true : false;
				}
				return false;
			}
		}, "SELECT COUNT(F01) FROM T6010_1 WHERE F01=? AND F03=1 ", phone);
		return count;
	}
	 */

	/**
	 * 多少秒内有无发送短信
	 */
	private int getSendSec(String phone, String type, int s) throws Throwable {
		return select(getConnection(FrontConst.DB_USER), new ItemParser<Integer>() {
			@Override
			public Integer parse(ResultSet rs) throws SQLException {
				int is = 0;
				if (rs.next()) {
					is = rs.getInt(1);
				}
				return is;
			}
		}, "SELECT COUNT(F01) FROM T6058 WHERE F02=? AND F05 <= CURRENT_TIMESTAMP() AND F05>= DATE_ADD(CURRENT_TIMESTAMP(),INTERVAL -? SECOND) AND F06=? ",
				phone, s, type);
	}

	@Override
	public int getSend(String phone) throws Throwable {
		return select(getConnection(FrontConst.DB_USER), new ItemParser<Integer>() {
			@Override
			public Integer parse(ResultSet rs) throws SQLException {
				int is = 0;
				if (rs.next()) {
					is = rs.getInt(1);
				}
				return is;
			}
		}, "SELECT COUNT(F01) FROM T6058 WHERE F02=? AND DATE(F05) = CURRENT_DATE()", phone);
	}

	@Override
	public void updatePassword(String password) throws Throwable {
		int acount = serviceResource.getSession().getAccountId();
		if (StringHelper.isEmpty(password) || acount <= 0) {
			throw new ParameterException("err_1015");
		}
		execute(getConnection(P2PConst.DB_USER), "UPDATE  T6010 SET F03=?,F11=? WHERE F01 = ?", password, IsPass.F,
				acount);

	}

	public IsPass sfxgmm() throws Throwable {
		int userId = serviceResource.getSession().getAccountId();
		String sql = "SELECT F11 FROM T6010 WHERE F01 = ?";
		return select(getConnection(FrontConst.DB_USER), new ItemParser<IsPass>() {
			@Override
			public IsPass parse(ResultSet resultSet) throws SQLException {
				IsPass str = IsPass.F;
				while (resultSet.next()) {
					str = EnumParser.parse(IsPass.class, resultSet.getString(1));
				}
				return str;
			}
		}, sql, userId);
	}

	public String getSign(String s1) throws Throwable {
		String sql = "SELECT MD5(CONCAT(?,IF(?='',CURRENT_DATE(),?)))";
		String r = selectString(FrontConst.DB_USER, sql, s1, SystemVariable.YZMJMC, SystemVariable.YZMJMC);
		if (StringHelper.isEmpty(r)) {
			throw new ParameterException("err_1015");
		}
		return r;

	}

	@Override
	public boolean isNickName(String accountName) throws Throwable {
		String sql = "SELECT F01 FROM T6010 WHERE F02=? or F04=? ";
		try (PreparedStatement ps = getConnection(FrontConst.DB_USER).prepareStatement(sql)) {
			ps.setString(1, accountName);
			ps.setString(2, accountName);
			try (ResultSet rs = ps.executeQuery()) {
				if (rs.next()) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public boolean isNickPhone(String phone) throws Throwable {
		return phone.matches("^(1)\\d{10}$");
	}

	@Override
	public void addJymm(String paypassword) throws Throwable {
		if (StringHelper.isEmpty(paypassword)) {
			throw new ParameterException("err_1016");

		}
		String dlmm=selectString(P2PConst.DB_USER, "SELECT F03 FROM T6010 WHERE F01=?", serviceResource.getSession().getAccountId());
		if(dlmm.equals(UnixCrypt.crypt(paypassword, DigestUtils.sha256Hex(paypassword)))){
			throw new ParameterException("err_1002");
		}
		
		String password = UnixCrypt.crypt(paypassword, DigestUtils.sha256Hex(paypassword));
//		execute(getConnection(P2PConst.DB_USER), "UPDATE T6011 SET F11=? WHERE F01=?", password,serviceResource.getSession().getAccountId());
		String sql="INSERT INTO T6011 SET F01=?,F11=? ON DUPLICATE KEY UPDATE F01=?,F11=?";
		execute(getConnection(P2PConst.DB_USER), sql, serviceResource.getSession().getAccountId(),password,serviceResource.getSession().getAccountId(),password);
	}

	@Override
	public void addSmrz(String name, String zjh, CertificateType certificateType) throws Throwable {
		if (StringHelper.isEmpty(name)) {
			throw new ParameterException("err_1017");

		}
		if (StringHelper.isEmpty(zjh)) {
			throw new ParameterException("err_1018");

		}
		if (certificateType == null) {
			throw new ParameterException("err_1019");
		}
		int count = selectInt(P2PConst.DB_USER, "SELECT COUNT(F04) FROM T6011 WHERE F04=?", zjh);
		if (count > 0) {
			throw new ParameterException("err_1020");
		}
		execute(getConnection(P2PConst.DB_USER),
				"UPDATE T6011 SET F02=?,F03=?,F04=?,F05=CURRENT_TIMESTAMP() WHERE F01=?", name, certificateType, zjh,
				serviceResource.getSession().getAccountId());

		
	}

	@Override
	public User getUser() throws Throwable {
		StringBuffer s=new StringBuffer("SELECT T6010.F02 username,T6011.F02 name,T6011.F04 zjh,T6023.F03 dj,T6023.F04 ky,T6010.F01 userid,t6011.F13 gjrz,t6010.F04 iphone,");
		s.append(" T6011.F05 cjsj,T6011.F03 zjlx, T6011.F07 code");
		s.append(" FROM t6010 LEFT JOIN t6011 ON t6010.F01=t6011.F01 LEFT JOIN T6023 ON T6010.F01=T6023.F01 WHERE T6010.F01=?");
		return select(getConnection(P2PConst.DB_USER), new ItemParser<User>() {
			@Override
			public User parse(ResultSet re) throws SQLException {
				User u = new User();
				while (re.next()) {
					u.username = re.getString(1);
					u.name = re.getString(2);
					u.zjh = re.getString(3);
					u.djje = re.getBigDecimal(4);
					u.kyje = re.getBigDecimal(5);
					u.userid = re.getInt(6);
					u.gjrz = EnumParser.parse(IsPass.class, re.getString(7));
					u.iphone=re.getString(8);
					u.cjsj=re.getTimestamp(9);
					u.certificateType=EnumParser.parse(CertificateType.class, re.getString(10));
					u.code=re.getString(11);
				}
				return u;
			}
		}, s.toString(),serviceResource.getSession().getAccountId());
	}
	
	@Override
	public User getUserBtc() throws Throwable {
		StringBuffer s=new StringBuffer("SELECT T6010.F02 username,T6011.F02 name,T6011.F04 zjh,T6023.F03 dj,T6023.F04 ky,T6010.F01 userid,t6011.F13 gjrz,t6010.F04 iphone,");
		s.append(" T6011.F05 cjsj,T6011.F03 zjlx,b.avail avail,b.frozen frozen");
		s.append(" FROM t6010 LEFT JOIN t6011 ON t6010.F01=t6011.F01 LEFT JOIN T6023 ON T6010.F01=T6023.F01 ");
		s.append("left join (select t6010.f01 userid,t6025.f04 avail, t6025.f05 frozen from t6025 left join t6010 on t6025.f02=t6010.f01 left join t6013 on t6025.f03=t6013.f01 where t6013.f02='btc') b on t6010.f01=b.userid ");
		s.append("WHERE T6010.F01=?");
		return select(getConnection(P2PConst.DB_USER), new ItemParser<User>() {
			@Override
			public User parse(ResultSet re) throws SQLException {
				User u = new User();
				while (re.next()) {
					u.username = re.getString(1);
					u.name = re.getString(2);
					u.zjh = re.getString(3);
					u.djje = re.getBigDecimal(12);
					u.kyje = re.getBigDecimal(11);
					u.userid = re.getInt(6);
					u.gjrz = EnumParser.parse(IsPass.class, re.getString(7));
					u.iphone=re.getString(8);
					u.cjsj=re.getTimestamp(9);
					u.certificateType=EnumParser.parse(CertificateType.class, re.getString(10));
				}
				return u;
			}
		}, s.toString(),serviceResource.getSession().getAccountId());
	}

	@Override
	public boolean gjsmrz() throws Throwable {
		boolean s=false;
		int count=selectInt(P2PConst.DB_USER,"SELECT COUNT(F01) FROM T6011 WHERE F01=? AND F13=?",
				serviceResource.getSession().getAccountId(),IsPass.S);
		if(count>0){
			s=true;
		}
		return s;
	}

	@Override
	public int szxx() throws Throwable {
		int i = 0;
		String gjsm = selectString(P2PConst.DB_USER, "SELECT F13 FROM T6011 WHERE F01=?",
				serviceResource.getSession().getAccountId());
		if (StringHelper.isEmpty(gjsm) || !gjsm.equals(IsPass.S.name())) {
			i =1;
		}
		String zjh = selectString(P2PConst.DB_USER, "SELECT F04 FROM T6011 WHERE F01=?",
				serviceResource.getSession().getAccountId());
		String name = selectString(P2PConst.DB_USER, "SELECT F02 FROM T6011 WHERE F01=?",
				serviceResource.getSession().getAccountId());
		if (StringHelper.isEmpty(zjh) || StringHelper.isEmpty(name)) {
			i =2;
		}
		String jymm = selectString(P2PConst.DB_USER, "SELECT F11 FROM T6011 WHERE F01=?",
				serviceResource.getSession().getAccountId());
		if (StringHelper.isEmpty(jymm)) {
			i =3;
		}
		
		
		return i;
	}

	
	@Override
	public List<Map<String, String>> getUserCapital() throws Throwable {
		String sql = "select b.F02 AS shortName,c.F04 as usable,c.f05 as frozen,b.F05 as pic from  t6013 AS b " + 
				"LEFT JOIN t6025 as c ON (b.F01=c.F03 AND c.F02=?)" + 
				" WHERE b.F01!=?";
		final FileStore fileStore = serviceResource.getResource(FileStore.class);
		Map<String,String> results[] =  selectAll(getConnection(P2PConst.DB_USER), new ArrayParser<Map<String,String>>() {
			
			@SuppressWarnings("unchecked")
			@Override
			public Map<String, String>[] parse(ResultSet rs) throws SQLException {
				
				List<Map<String,String>> listMap = new ArrayList<Map<String,String>>();
				while(rs.next()) {
					Map<String,String> perCoin = new HashMap<String,String>();
					perCoin.put("shortName", rs.getString(1));
					perCoin.put("usable", String.valueOf(rs.getDouble(2)));
					perCoin.put("frozen", String.valueOf(rs.getDouble(3)));
					perCoin.put("pic", rs.getString(4)!=null?String.valueOf(fileStore.getURL(rs.getString(4))):"");
					listMap.add(perCoin);
				}
				if(listMap.size()==0) return null;
				Map<String,String> ary[] = new HashMap[listMap.size()];
				int i=0;
				for(Map<String,String> m:listMap) {
					ary[i++] = m;
				}
				return ary;
			}
		}, sql, serviceResource.getSession().getAccountId(),16);
		
		List<Map<String,String>> list = Arrays.asList(results);
		return list;
	}
	


	
}
